
'use strict'

// 类以及继承

class Polygon {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }

    get name() {
        return this._name;
    }

    set name(somename) {
        this._name = somename;
    }

    area() {
        return this.width * this.height;
    }

}


class MultiPolygon extends Polygon {
    constructor(height, width) {
        super(height, width);
    }

    area() {
        return 2 * super.area();
    }

    static distance() {
        return 3;
    }
}




var p = new Polygon(3, 4);
p.name = "p1";
console.log(p.name);
console.log(p.area());

var p2 = new MultiPolygon(4, 5);
console.log(p2.area());
console.log(MultiPolygon.distance());
console.log(MultiPolygon.prototype);


// 生成器 generator

function* helloWorldGenerator() {
    yield 'hello';

    console.log(yield 'val');

    yield 'world';
    return 'ending';
}

var hw = helloWorldGenerator();

console.log(hw.next());
console.log(hw.next());
console.log(hw.next());
console.log(hw.next());
console.log(hw.next());


function* func() {
    for (var index = 0; true; index++) {
        var element = yield index;
        if (element) {
            index = -1;
        }
    }
}

var func1 = func();

console.log(func1.next());
console.log(func1.next());
console.log(func1.next(true));
console.log(func1.next());
console.log(func1.next());
console.log(func1.next(true));


function* foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return x + y + z;
}
var fooa = foo(5);
console.log(fooa.next());
console.log(fooa.next());
console.log(fooa.next());

var foob = foo(5);
console.log(Array.from(foob));

// 斐波那契数列

function* fibonacci() {
    let prev = 0;
    let cuur = 1;
    for (; ;) {
        let r = prev + cuur;
        prev = cuur;
        cuur = r;
        yield cuur;
    }
}

for (let n of fibonacci()) {
    if (n > 1000) {
        break;
    }
    console.log(n);
}

function* bar1() {
    yield 'a';
    yield 'b';
};

function* bar2() {
    yield 'c';
    yield* bar1();
    yield 'd';
}
console.log(Array.from(bar2()));


function* genFuncWithReturn() {
    yield 'a';
    yield 'b';
    //return 'the result';
};

function* logReturned(genObj) {
    let result = yield* genObj;
    console.log(result);
}

console.log(Array.from(logReturned(genFuncWithReturn())));


function* g() {

}
g.prototype.hello = function () {
    return 'hi';
}
let obj = g();
console.log(obj instanceof g);
console.log(obj.hello());


// Generator函数是不能直接作为构造函数使用的。
// 可以采用下边的变通方法：首先生成一个空对象，
// 然后通过bind方法绑定Generator函数的内部this。
// 但是这样又带来的一个问题是生成器函数的原型上的方法又没办法用了。


function* F() {
    yield this.x = 2;
    yield this.y = 3;
};

F.prototype.hello = function () {
    return 'hello world';
}

var obj1 = {};
var f = F.bind(obj1)();

f.next();
f.next();
f.next();

console.log(obj1.x);
console.log(obj1.y);
console.log(obj1.prototype);


// 实现状态机
function* state(_) {
    while (true) {
        yield _;
        console.log('Tick');
        yield _;
        console.log('Tock');
    }
}

var clock = state();
clock.next();
clock.next();
clock.next();
clock.next();
clock.next();
clock.next();
clock.next();
clock.next();



// 对象创建测试

var proto = {
    "name": '张三',
    "age": 25,
    get shut() {
        return this.name;
    }
};


var objt = Object.create(proto);

console.log(proto);
console.log(objt);
console.log(objt.shut);


function calldemo() {

    var args = Array.prototype.slice.call(arguments, 1);
    console.log(args);
}

calldemo("s", "t", "tx");


// co(tj大神写的关于封装generator方法和promise的模块) 的一个最简单的模拟实现

function co(generator) {
    return new Promise(function (resolve, reject) {
        var gen = generator();
        function next(err, result) {
            if (err) {              // 异常
                reject(err);
            }
            var step = gen.next(result);
            if (step.done) {        // 结束
                resolve(step.value || result);
            }
            else {                  // 继续执行
                step.value.then(function (val) {
                    next(null, val);
                }).catch(function (err) {
                    reject(err);
                });
            }
        }
        next();
    });
};


co(function* () {
    var c1 = yield new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('1ms');
            resolve('1ms');
        }, 1000);
    });

    var c2 = yield new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('3ms' + c1);
            resolve('3ms' + c1);
            //reject("err:4ms");
        }, 3000);
    });

    return c2 + "  ---this value is returned";

}).then(function (val) {
    console.log('doned:' + val);
}).catch(function (err) {
    console.log(err);
});




// es6中的二进制数组
// 简单的瞅了一眼，还是蛮复杂的。不过呢，也就这样吧。
var buf = new ArrayBuffer(32);
var view = new Int32Array(buf);
view[0] = 2;
view[1] = 3;
view[2] = 4;
view[3] = 5;

console.log(view[2]); 



// 解构赋值不支持？？
// 确实不支持
// var o1 = { "name": 'zs', "age": 23 };
// const {oname, oage} = o1;
// console.log(oname);


// 箭头函数
// 效率基本一样的
let count = 10;

console.time("t1");
for (var index = 0; index < count; index++) {
    (() => {
        var x = 488549948 * 4394834;
    })();
}

console.timeEnd('t1');

console.time("t2");
for (var index1 = 0; index1 < count; index1++) {
    (function () {
        var x = 488549948 * 4394834;
    })();
}
console.timeEnd('t2');

















































